import os

from hruntools.hrunutils import checkDuplDict, delDictItem
from utils.config.propertiesExt import ExtProperties


class TestcaseJson:
    """
     # 预处理testcase 后 给机器run  —— 复杂化
        将config中的内容，分散到 testcase
    比如：headers、validate、variable
    """
    def preHandleConfig(self, otc, workdir):
        # 自动处理config 中的headers(公共header)，添加到request.headers
        self._handle_configheaders(otc )
        self._handle_configValidate(otc)
        # 自动处理 config 中的configfile, 转换为变量
        self._handle_configfile(otc, workdir)

    def _handle_configheaders(self, oTestcase):
        # 处理config中的headers
        # 将headers添加到testcase中

        def handle_Single_headers(oheader, cheader):
            # 将config 的header ，复制到testcase header，并排除重复内容
            for k, v in cheader.items():
                if k not in oheader:
                    oheader[k] = v

            return oheader

        xTcs = {}
        # 1 提取config headers
        cHeaders = None
        if isinstance(oTestcase, dict):
            if 'headers' not in oTestcase['config']:
                raise Exception("Error: 没有找config 中的headers")

            cHeaders = oTestcase['config']['headers']
            xTcs = oTestcase['teststeps']

        elif isinstance(oTestcase, list):
            if len(oTestcase) > 1:
                raise Exception('暂时不支持多个testcase 列表')

            if 'config' not in oTestcase[0] or 'headers' not in oTestcase[0]['config']:
                return

            cHeaders = oTestcase[0]['config']['headers']
            xTcs = oTestcase[0]['teststeps']

        if cHeaders == None: return

        # 2 扫描testcase
        for tc in xTcs:
            if 'request' not in tc:
                continue
            xheader = tc['request'].get('headers', {})
            tc['request']['headers'] = handle_Single_headers(xheader, cHeaders)

        # print(xTcs)

    def _handle_configValidate(self, oTestcase):
        # 处理config中的Validate
        # 将Validate添加到testcase中

        def handle_Single_validates(ovalidate, cvalidate):
            # 将config 的validates ，复制到testcase validates，并排除重复内容
            for v in cvalidate:
                if v not in ovalidate:
                    ovalidate.append(v)

            return ovalidate

        xTcs = {}
        # 1 提取config headers
        cvalidates = None
        if isinstance(oTestcase, dict):
            if 'validate' not in oTestcase['config']:
                raise Exception("Error: 没有找config 中的validate")

            cvalidates = oTestcase['config']['validate']
            xTcs = oTestcase['teststeps']

        elif isinstance(oTestcase, list):
            if len(oTestcase) > 1:
                raise Exception('暂时不支持多个testcase 列表')

            if 'config' not in oTestcase[0] or 'validate' not in oTestcase[0]['config']:
                return

            cvalidates = oTestcase[0]['config']['validate']
            xTcs = oTestcase[0]['teststeps']

        if cvalidates == None: return

        # 2 扫描testcase
        for tc in xTcs:
            xvalidate = tc.get('validate', [])
            try:
                tc['validate'] = handle_Single_validates(xvalidate, cvalidates)
            except:
                print("Wrong :" + str(tc))
                raise Exception("validate wrong!")

    def _handle_configfile(self, oTestcase, workDir):
        # oTestcase 必须是 Dict类型
        # 处理config.configfile  , 并将文件中的变量 放置到config.variables
        if not isinstance(oTestcase, dict) or 'config' not in oTestcase \
                or 'configfile' not in oTestcase['config']:
            return

        ovars = oTestcase['config'].get('variables', {} )   #[''] if 'variables' in oTestcase['config'] else {}
        configfile = oTestcase['config']['configfile']

        filepath = configfile
        if not os.path.isfile(filepath):
            # 拼接到工作目录
            filepath = os.path.join(workDir, configfile)
            if not os.path.isfile(filepath):
                filepath = os.path.join(workDir, "testcases/", configfile)
                if not os.path.isfile(filepath):
                    return
        # 读取配置文件
        prop = ExtProperties(filepath)
        for k, v in prop.getPropertyDict().items():
            if not k in ovars:
                ovars[k] = v

        oTestcase['config']['variables'] = ovars


class TestcaseHandler:
    """
    预处理 testcase 后 保存 给人看——简化
    收集、聚合 testcase重复的内容，到 config
    比如：headers、validates
    """
    def __init__(self, oConfig, oTestcase):
        self.oTestCase = oTestcase
        self.oConfig = oConfig

    def handleHeaders(self):
        oname = 'headers'

        def setItem(oDict, oitem):
            oDict['request'][oname] = oitem

        self._handlePublicItem(oname, setItem, lambda o: o['request'])
        return self

    def handleValidate(self):
        oname = 'validate'

        def setItem(oDict, oitem):
            oDict[oname] = oitem

        self._handlePublicItem(oname, setItem, getItem=lambda o: o)
        return self

    def _handlePublicItem(self, oname, setItem, getItem):
        # 处理重复的validate 放到 config.validate

        # 扫描 hrun json 检查重复validate，放到 odicts
        oitems = None
        if oname in getItem(self.oTestCase[0]):
            oitems = getItem(self.oTestCase[0])[oname].copy()
        else:  # 第一条用例没有 说明没有共有 header
            return

        for oTc in self.oTestCase:
            if oname in getItem(oTc):
                oitems = checkDuplDict(oitems, getItem(oTc)[oname])

        if len(oitems) == 0: return

        # headers总是 提取Authorization
        if oname == "headers": oitems['Authorization'] = "auth token"

        # 清理 testcase 中重复headers
        for oTc in self.oTestCase:
            oo = getItem(oTc)[oname]
            setItem(oTc, delDictItem(oitems, oo))

        # odicts 放到config.validate
        if len(oitems) > 0:
            self.oConfig[oname] = oitems